home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene 96
/
Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso
/
misc
/
coding
/
cp2dekit
/
samples
/
wavplay.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1996-12-29
|
13KB
|
582 lines
//***************************************************************************
//
// this file is (c) '94-'96 Niklas Beisert
//
// this file is part of the cubic player development kit.
// you may only use/modify/spread this file under the terms stated
// in the cubic player development kit accompanying documentation.
//
//***************************************************************************
// player device example
#include <string.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
//#include <io.h>
#include "binfile.h"
#include "poll.h"
#include "player.h"
#include "wave.h"
static unsigned char stereo;
static unsigned char bit16;
static unsigned char signedout;
static unsigned long samprate;
static unsigned char reversestereo;
static unsigned short *buf16;
static unsigned short __far16 *segbuf16;
static unsigned long bufpos;
static int buflen;
static void *plrbuf;
static unsigned short *cliptabl;
static unsigned short *cliptabr;
static unsigned long amplify;
static unsigned long voll,volr;
static char convtostereo;
static binfile *wavefile;
static char wavestereo;
static char wave16bit;
static unsigned long waverate;
static unsigned long wavepos;
static unsigned long wavelen;
static unsigned long waveoffs;
static unsigned char *wavebuf;
static unsigned long wavebuflen;
static unsigned long wavebufpos;
static unsigned long wavebuffpos;
static unsigned long wavebufread;
static unsigned long wavebufrate;
static char active;
static char looped;
static char donotloop;
static unsigned long bufloopat;
static char pause;
extern "C" void mixClipAlt(unsigned short *dst, const unsigned short *src, unsigned long len, const unsigned short *tab);
#pragma aux mixClipAlt parm [edi] [esi] [ecx] [ebx] modify [eax edx]
extern "C" void mixClipAlt2(unsigned short *dst, const unsigned short *src, unsigned long len, const unsigned short *tab);
#pragma aux mixClipAlt2 parm [edi] [esi] [ecx] [ebx] modify [eax edx]
signed long muldiv(signed long a, signed long b, unsigned long c);
#pragma aux muldiv parm [eax] [edx] [ebx] value [eax] = "imul edx" "idiv ebx"
static void mixCalcClipTab(unsigned short *ct, signed long amp)
{
signed long i,j,a,b;
a=-amp;
for (i=0; i<256; i++)
ct[i+768]=(a+=amp)>>16;
for (i=0; i<256; i++)
ct[i+1024]=0;
b=0x800000-(amp<<7);
for (i=0; i<256; i++)
{
if (b<0x000000)
if ((b+amp)<0x000000)
{
((unsigned short **)ct)[i]=ct+1024;
ct[i+512]=0x0000;
}
else
{
a=0;
for (j=0; j<256; j++)
{
ct[j+1280]=(((a>>8)+b)<0x000000)?0x0000:(((a>>8)+b)>>8);
a+=amp;
}
((unsigned short **)ct)[i]=ct+1280;
ct[i+512]=0x0000;
}
else
if ((b+amp)>0xFFFFFF)
if (b>0xFFFFFF)
{
((unsigned short **)ct)[i]=ct+1024;
ct[i+512]=0xFFFF;
}
else
{
a=0;
for (j=0; j<256; j++)
{
ct[j+1536]=(((a>>8)+b)>0xFFFFFF)?0x0000:((((a>>8)+b)>>8)+1);
a+=amp;
}
((unsigned short **)ct)[i]=ct+1536;
ct[i+512]=0xFFFF;
}
else
{
((unsigned short **)ct)[i]=ct+768;
ct[i+512]=b>>8;
}
b+=amp;
}
}
static int clipbusy=0;
static void calccliptab(signed long ampl, signed long ampr)
{
clipbusy++;
if (!stereo)
{
ampl=(abs(ampl)+abs(ampr))>>1;
ampr=0;
}
mixCalcClipTab(cliptabl, abs(ampl));
mixCalcClipTab(cliptabr, abs(ampr));
int i;
if (signedout)
for (i=0; i<256; i++)
{
cliptabl[i+512]^=0x8000;
cliptabr[i+512]^=0x8000;
}
clipbusy--;
}
static void timerproc()
{
if (clipbusy)
return;
clipbusy++;
unsigned long bufplayed=plrGetBufPos()>>(stereo+bit16);
unsigned long bufdelta;
unsigned long pass2;
if (bufplayed==bufpos)
{
clipbusy--;
return;
}
int quietlen=0;
bufdelta=(buflen+bufplayed-bufpos)%buflen;
if (wavebuflen!=wavelen)
{
int towrap=muldiv((((wavebuflen+wavebufread-wavebufpos-1)%wavebuflen)>>(wavestereo+wave16bit)), 65536, wavebufrate);
if (bufdelta>towrap)
quietlen=bufdelta-towrap;
}
if (pause)
quietlen=bufdelta;
int toloop=muldiv(((bufloopat-wavebufpos)>>(wave16bit+wavestereo)), 65536, wavebufrate);
if (looped)
toloop=0;
bufdelta-=quietlen;
if (bufdelta>=toloop)
{
looped=1;
if (donotloop)
{
quietlen+=bufdelta-toloop;
bufdelta=toloop;
}
}
if (bufdelta)
{
if ((bufpos+bufdelta)>buflen)
pass2=bufpos+bufdelta-buflen;
else
pass2=0;
plrClearBuf(buf16, bufdelta*2, 1);
int i;
if (wave16bit)
{
if (wavestereo)
for (i=0; i<bufdelta; i++)
{
unsigned long v=*(unsigned long*)(wavebuf+wavebufpos)^0x80008000;
if (reversestereo)
v=_lrotl(v, 16);
*(unsigned long*)(buf16+2*i)=v;
wavebuffpos+=wavebufrate;
wavebufpos+=(wavebuffpos>>16)*4;
wavebuffpos&=0xFFFF;
if (wavebufpos>=wavebuflen)
wavebufpos-=wavebuflen;
}
else
for (i=0; i<bufdelta; i++)
{
buf16[2*i+1]=buf16[2*i]=*(unsigned short*)(wavebuf+wavebufpos)^0x8000;
wavebuffpos+=wavebufrate;
wavebufpos+=(wavebuffpos>>16)*2;
wavebuffpos&=0xFFFF;
if (wavebufpos>=wavebuflen)
wavebufpos-=wavebuflen;
}
}
else
{
if (wavestereo)
for (i=0; i<bufdelta; i++)
{
if (reversestereo)
{
buf16[2*i+1]=wavebuf[wavebufpos]<<8;
buf16[2*i]=wavebuf[wavebufpos+1]<<8;
}
else
{
buf16[2*i]=wavebuf[wavebufpos]<<8;
buf16[2*i+1]=wavebuf[wavebufpos+1]<<8;
}
wavebuffpos+=wavebufrate;
wavebufpos+=(wavebuffpos>>16)*2;
wavebuffpos&=0xFFFF;
if (wavebufpos>=wavebuflen)
wavebufpos-=wavebuflen;
}
else
for (i=0; i<bufdelta; i++)
{
buf16[2*i+1]=buf16[2*i]=wavebuf[wavebufpos]<<8;
wavebuffpos+=wavebufrate;
wavebufpos+=wavebuffpos>>16;
wavebuffpos&=0xFFFF;
if (wavebufpos>=wavebuflen)
wavebufpos-=wavebuflen;
}
}
if (!stereo)
{
for (i=0; i<bufdelta; i++)
buf16[i]=(buf16[2*i]+buf16[2*i+1])>>1;
}
if (bit16)
{
if (stereo)
{
mixClipAlt2((unsigned short*)plrbuf+bufpos*2, buf16, bufdelta-pass2, cliptabl);
mixClipAlt2((unsigned short*)plrbuf+bufpos*2+1, buf16+1, bufdelta-pass2, cliptabr);
if (pass2)
{
mixClipAlt2((unsigned short*)plrbuf, buf16+2*(bufdelta-pass2), pass2, cliptabl);
mixClipAlt2((unsigned short*)plrbuf+1, buf16+2*(bufdelta-pass2)+1, pass2, cliptabr);
}
}
else
{
mixClipAlt((unsigned short*)plrbuf+bufpos, buf16, bufdelta-pass2, cliptabl);
if (pass2)
mixClipAlt((unsigned short*)plrbuf, buf16+bufdelta-pass2, pass2, cliptabl);
}
}
else
{
if (stereo)
{
mixClipAlt2(buf16, buf16, bufdelta, cliptabl);
mixClipAlt2(buf16+1, buf16+1, bufdelta, cliptabr);
}
else
mixClipAlt(buf16, buf16, bufdelta, cliptabl);
plr16to8((unsigned char*)plrbuf+(bufpos<<stereo), buf16, (bufdelta-pass2)<<stereo);
if (pass2)
plr16to8((unsigned char*)plrbuf, buf16+((bufdelta-pass2)<<stereo), pass2<<stereo);
}
bufpos+=bufdelta;
if (bufpos>=buflen)
bufpos-=buflen;
}
bufdelta=quietlen;
if (bufdelta)
{
if ((bufpos+bufdelta)>buflen)
pass2=bufpos+bufdelta-buflen;
else
pass2=0;
if (bit16)
{
plrClearBuf((unsigned short*)plrbuf+(bufpos<<stereo), (bufdelta-pass2)<<stereo, !signedout);
if (pass2)
plrClearBuf((unsigned short*)plrbuf, pass2<<stereo, !signedout);
}
else
{
plrClearBuf(buf16, bufdelta<<stereo, !signedout);
plr16to8((unsigned char*)plrbuf+(bufpos<<stereo), buf16, (bufdelta-pass2)<<stereo);
if (pass2)
plr16to8((unsigned char*)plrbuf, buf16+((bufdelta-pass2)<<stereo), pass2<<stereo);
}
bufpos+=bufdelta;
if (bufpos>=buflen)
bufpos-=buflen;
}
plrAdvanceTo(bufpos<<(stereo+bit16));
clipbusy--;
}
void wpIdle()
{
if ((wavelen==wavebuflen)||!active)
return;
unsigned long clean=(wavebufpos+wavebuflen-wavebufread)%wavebuflen;
if (clean*8>wavebuflen)
{
while (clean)
{
wavefile->seek(waveoffs+wavepos);
int read=clean;
if ((wavebufread+read)>wavebuflen)
read=wavebuflen-wavebufread;
if ((wavepos+read)>=wavelen)
{
read=wavelen-wavepos;
bufloopat=wavebufread+read;
}
if (read>0x10000)
read=0x10000;
wavefile->read(wavebuf+wavebufread, read);
wavebufread=(wavebufread+read)%wavebuflen;
wavepos=(wavepos+read)%wavelen;
clean-=read;
}
}
}
unsigned char wpOpenPlayer(binfile &wav, int tostereo)
{
if (!plrPlay)
return 0;
convtostereo=tostereo;
cliptabl=new unsigned short[1793];
cliptabr=new unsigned short[1793];
if (!cliptabl||!cliptabr)
{
delete cliptabl;
delete cliptabr;
return 0;
}
wavefile=&wav;
if (wavefile->getul()!=0x46464952)
return 0;
wavefile->getul();
if (wavefile->getul()!=0x45564157)
return 0;
while (1)
{
int stat;
if (wavefile->egetul(stat)==0x20746D66)
break;
if (!stat)
return 0;
wavefile->seekcur(wavefile->getul());
}
if (wavefile->getul()!=16)
return 0;
if (wavefile->getus()!=1)
return 0;
wavestereo=wavefile->getus()==2;
waverate=wavefile->getul();
wavefile->getul();
wavefile->getus();
wave16bit=wavefile->getus()==16;
while (1)
{
int stat;
if (wavefile->egetul(stat)==0x61746164)
break;
if (!stat)
return 0;
wavefile->seekcur(wavefile->getul());
}
wavelen=wavefile->getul();
waveoffs=wavefile->tell();
if (!wavelen)
return 0;
wavebuflen=1024*1024;
if (wavebuflen>wavelen)
{
wavebuflen=wavelen;
bufloopat=wavebuflen;
}
else
bufloopat=0x40000000;
wavebuf=new unsigned char [wavebuflen];
if (!wavebuf)
{
wavebuflen=256*1024;
wavebuf=new unsigned char [wavebuflen];
if (!wavebuf)
return 0;
}
wavelen=wavelen&~(1<<(wavestereo+wave16bit)-1);
wavebufpos=0;
wavebuffpos=0;
wavebufread=0;
wavefile->read(wavebuf, wavebuflen);
wavepos=wavebuflen;
plrSetOptions(waverate, (convtostereo||wavestereo)?(PLR_STEREO|PLR_16BIT):PLR_16BIT);
if (!plrOpenPlayer(plrbuf, buflen))
return 0;
stereo=!!(plrOpt&PLR_STEREO);
bit16=!!(plrOpt&PLR_16BIT);
signedout=!!(plrOpt&PLR_SIGNEDOUT);
reversestereo=!!(plrOpt&PLR_REVERSESTEREO);
samprate=plrRate;
wavebufrate=muldiv(65536, waverate, samprate);
pause=0;
looped=0;
amplify=65536;
voll=256;
volr=256;
calccliptab((amplify*voll)>>8, (amplify*volr)>>8);
buf16=new unsigned short [buflen*2];
if (!buf16)
{
plrClosePlayer();
delete buf16;
return 0;
}
bufpos=0;
if (!pollInit(timerproc))
{
plrClosePlayer();
return 0;
}
active=1;
return 1;
}
void wpClosePlayer()
{
active=0;
pollClose();
plrClosePlayer();
delete wavebuf;
delete buf16;
delete cliptabl;
delete cliptabr;
}
char wpLooped()
{
return looped;
}
void wpSetLoop(unsigned char s)
{
donotloop=!s;
}
void wpPause(unsigned char p)
{
pause=p;
}
void wpSetAmplify(unsigned long amp)
{
amplify=amp;
calccliptab((amplify*voll)>>8, (amplify*volr)>>8);
}
void wpSetSpeed(unsigned short sp)
{
if (sp<32)
sp=32;
wavebufrate=muldiv(256*sp, waverate, samprate);
}
void wpSetVolume(unsigned char vol, signed char bal, signed char pan, unsigned char opt)
{
voll=vol*4;
volr=vol*4;
if (bal<0)
volr=(volr*(64+bal))>>6;
else
voll=(voll*(64-bal))>>6;
wpSetAmplify(amplify);
}
unsigned long wpGetPos()
{
if (wavelen==wavebuflen)
return wavebufpos>>(wavestereo+wave16bit);
else
return ((wavepos+wavelen-wavebuflen+((wavebufpos-wavebufread+wavebuflen)%wavebuflen))%wavelen)>>(wavestereo+wave16bit);
}
void wpGetInfo(waveinfo &i)
{
i.pos=wpGetPos();
i.len=wavelen>>(wavestereo+wave16bit);
i.rate=waverate;
i.stereo=wavestereo;
i.bit16=wave16bit;
}
void wpSetPos(signed long pos)
{
pos=((pos<<(wave16bit+wavestereo))+wavelen)%wavelen;
if (wavelen==wavebuflen)
wavebufpos=pos;
else
{
if (((pos+wavebuflen)>wavepos)&&(pos<wavepos))
wavebufpos=(wavebufread-(wavepos-pos)+wavebuflen)%wavebuflen;
else
{
wavepos=pos;
wavebufpos=0;
wavebufread=1<<(wave16bit+wavestereo);
}
}
}